
#include <transformationeditwidget.h>
#include <math/quaternion.h>
#include <math/vector.h>

TransformationEditWidget::TransformationEditWidget(QWidget *parent)
  : QWidget(parent)
  , _transformer (0)
{
  _gui.setupUi (this);
}

void TransformationEditWidget::SetTransformer(ceTransformer *transformer)
{
  _transformer = transformer;
}

void TransformationEditWidget::UpdateGUI()
{
  bool enabled = _transformer && _transformer->IsValid();

  _gui.groupBoxRot->setEnabled(enabled);
  _gui.groupBoxTrans->setEnabled(enabled);

  ceVector3f trans (0.0f, 0.0f, 0.0f);
  ceVector3f rot (0.0f, 0.0f, 0.0f);
  if (enabled)
    {
      ceMatrix4f& mat = _transformer->GetTransformation();
      trans = mat.GetTranslation();

      ceQuaternion q (mat);

      float angle = -q.GetAngle() * 180.0f / M_PI;
      ceVector3f axis = q.GetAxis();
      rot = axis * angle;
    }

  _gui.spinBoxRotX->blockSignals(true);
  _gui.spinBoxRotY->blockSignals(true);
  _gui.spinBoxRotZ->blockSignals(true);
  _gui.spinBoxTransX->blockSignals(true);
  _gui.spinBoxTransY->blockSignals(true);
  _gui.spinBoxTransZ->blockSignals(true);
  _gui.spinBoxRotX->setValue(rot.x);
  _gui.spinBoxRotY->setValue(rot.y);
  _gui.spinBoxRotZ->setValue(rot.z);
  _gui.spinBoxTransX->setValue(trans.x);
  _gui.spinBoxTransY->setValue(trans.y);
  _gui.spinBoxTransZ->setValue(trans.z);
  _gui.spinBoxRotX->blockSignals(false);
  _gui.spinBoxRotY->blockSignals(false);
  _gui.spinBoxRotZ->blockSignals(false);
  _gui.spinBoxTransX->blockSignals(false);
  _gui.spinBoxTransY->blockSignals(false);
  _gui.spinBoxTransZ->blockSignals(false);
}

void TransformationEditWidget::ReadMatrix(ceMatrix4f &matrix)
{
  ceVector3f trans (
        _gui.spinBoxTransX->value(),
        _gui.spinBoxTransY->value(),
        _gui.spinBoxTransZ->value());

  ceVector3f axis (
        _gui.spinBoxRotX->value(),
        _gui.spinBoxRotY->value(),
        _gui.spinBoxRotZ->value());


  float angle = axis.Length();
  if (angle == 0.0f)
    {
      axis = ceVector3f (0, 0, 1);
    }
  else
    {
      axis.Normalize();
    }

  matrix.SetIdentity();
  matrix.SetRotation(axis, angle);
  matrix.SetTranslation(trans);
}


void TransformationEditWidget::on_spinBoxTransX_valueChanged(double d)
{
  Apply();
}

void TransformationEditWidget::on_spinBoxTransY_valueChanged(double d)
{
  Apply();
}

void TransformationEditWidget::on_spinBoxTransZ_valueChanged(double d)
{
  Apply();
}
void TransformationEditWidget::on_spinBoxRotX_valueChanged(double d)
{
  Apply();
}

void TransformationEditWidget::on_spinBoxRotY_valueChanged(double d)
{
  Apply();
}

void TransformationEditWidget::on_spinBoxRotZ_valueChanged(double d)
{
  Apply();
}

void TransformationEditWidget::Apply()
{
  if (!_transformer)
    {
      return;
    }

  ReadMatrix(_transformer->GetTransformation());
  _transformer->UpdateTransformation();
  emit TransformationChanged ();
}

void TransformationEditWidget::Reset()
{
  _transformer->ResetTransformation();
  UpdateGUI();
  emit TransformationChanged();
}
